#include "stdafx.h"
#include <stdio.h>
#include "LavaParser.h"

#include <assert.h>

#define IS_WHITESPACE(c) ( (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n'))

CLavalampParser::CLavalampParser() : CXMLParser (LAVA_BUF_SIZE)
{
}
   
CLavalampParser::~CLavalampParser()
{
}
   
int32 CLavalampParser::GetNextLavalampInfoLength()
{
   /* Find the next <tr> under <tbody> */
   int32 nRet;
   LPXmlContent pContent = NULL;
   if (m_nCount) {
      pContent = m_arrayContents[m_nCount-1];
   }
      
   while (!IsTrUnderTboday(pContent)) {
      int nRet = GetNextInPreorder (&pContent);
      if (nRet < 0) {
         return nRet;
      }
   };   
   
   nRet = ConcatenateCDataUnder(pContent);
   if (nRet < 0) {
      return nRet;
   }
   return strlen(m_szTxt);
}
   
int32 CLavalampParser::CopyLavalampInfo(char* buf, size_t bufsize)
{
   strncpy (buf, m_szTxt, bufsize);
   return 0;
}

bool CLavalampParser::IsTrUnderTboday(LPXmlContent pContent)
{
   if (!pContent) {
      return false;
   }
   if (pContent->nType != XML_CONTENT_ELEMENT_TYPE) {
      return false;
   }
   if (strcmp (pContent->element.pName, TR_ELEMENT) != 0) {
      return false;
   }
   LPXmlContent pParent = pContent->pParent;
   if (!pParent) {
      return false;
   }
   if (pParent->nType != XML_CONTENT_ELEMENT_TYPE) {
      return false;
   }
   if (strcmp (pParent->element.pName, TBODY_ELEMENT) != 0) {
      return false;
   }
   return true;
} 

int32 CLavalampParser::ConcatenateCDataUnder(LPXmlContent pContent)
{
   assert (pContent);
   assert (pContent->nType == XML_CONTENT_ELEMENT_TYPE);
   LPXmlContent pParent = pContent->pParent;
   LPXmlContent pSub = NULL;
   
   int nIdx = 0;
   memset(m_szTxt, 0, sizeof(m_szTxt));
   /* if we find one element whose parent is same as current parent,
    *  then pContent has met this end tag.
    * Note: this depends on the parser's behave that it return a CDATA,
    *  even in "<a></a>" case. 
    */
   do {
      int nRet = GetNextInPreorder (&pSub);
      if (nRet < 0 || !pSub) {
         return nRet;
      }
      if (pSub->nType ==XML_CONTENT_CDATA_TYPE) {
         Concatenate (&nIdx, pSub->cdata.pCDATA);
      }
   } while (pParent != pSub->pParent);
   return 0;
}

void CLavalampParser::Concatenate(int* pnDstIdx, const char* szSrc)
{
   assert (pnDstIdx);
   assert (*pnDstIdx >= 0 && *pnDstIdx < sizeof (m_szTxt));
   
   if (*pnDstIdx == sizeof(m_szTxt) || szSrc == NULL) {
      return;
   }
   
   unsigned int nSrcIdx = 0;
   while ((nSrcIdx < strlen(szSrc)) && (*pnDstIdx < sizeof (m_szTxt)-1 )) {
      if (IS_WHITESPACE (szSrc[nSrcIdx])) {
         if (*pnDstIdx > 0 && m_szTxt[*pnDstIdx-1] != ' ') {
            m_szTxt[(*pnDstIdx)++] = ' ';
         }
      } else {
         m_szTxt[(*pnDstIdx)++] = szSrc[nSrcIdx];
      }
      nSrcIdx++;   
   }
}
